﻿using System;

namespace FinMkts
{
    /// <summary>
    /// An amount of some thing
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public struct Quantity<T> : IEquatable<Quantity<T>> where T : struct
    {
        /// <summary>
        /// The quanity of the <see cref="Units"/>
        /// </summary>
        public T Amount { get; private set; }

        /// <summary>
        /// The type of thing
        /// </summary>
        public Unit Units { get; private set; }

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="amount"></param>
        /// <param name="unit"></param>
        public Quantity(T amount, Unit unit) : this()
        {
            Amount = amount;
            Units = unit;
        }

        #region equality

        public bool Equals(Quantity<T> other)
        {
            return other.Amount.Equals(Amount) && Equals(other.Units, Units);
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (obj.GetType() != typeof (Quantity<T>)) return false;
            return Equals((Quantity<T>) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (Amount.GetHashCode()*397) ^ Units.GetHashCode();
            }
        }

        public static bool operator ==(Quantity<T> left, Quantity<T> right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(Quantity<T> left, Quantity<T> right)
        {
            return !left.Equals(right);
        }

        #endregion

        public override string ToString()
        {
            return string.Format("{0} {1}", Amount, Units);
        }
    }
}